
import java.util.Arrays;

import javax.swing.JTextField;



public class Solver {
    JTextField[][] textRutor;
    
    MyInteger[][] rutor;
    MyInteger[][] rader;
    MyInteger[][] kolumner;
    int x = 0;

    
    public Solver (MyInteger[][] rutor, MyInteger[][] rader, 
            MyInteger[][] kolumner, JTextField[][] textRutor){
        this.rutor = rutor;
        this.rader = rader;
        this.kolumner = kolumner;
        this.textRutor = textRutor;
        

    }
    
    public boolean possibleSudoku() {
        
        for (int i = 0; i <= 8; i++) {
            boolean[] radExist = new boolean[9];
            boolean[] rutExist = new boolean[9];
            boolean[] kolExist = new boolean[9];
            
            Arrays.fill(radExist, false);
            Arrays.fill(rutExist, false);
            Arrays.fill(kolExist, false);
            
            for (int j = 0; j <= 8; j++) {
                
                int radTemp = rader[i][j].getValue();
                int rutTemp = rutor[i][j].getValue();
                int kolTemp = kolumner[i][j].getValue();

                if (radTemp == 0) {
                    ;
                } else {
                    if (!radExist[radTemp - 1]) {
                        radExist[radTemp - 1] = true;
                    } else {
                        return false;
                    }
                }
                
                if (rutTemp == 0) {
                    ;
                } else {
                    if (!rutExist[rutTemp - 1]) {
                        rutExist[rutTemp - 1] = true;
                    } else {
                        return false;
                    }
                }
                
                if (kolTemp == 0) {
                    ;
                } else {
                    if (!kolExist[kolTemp - 1]) {
                        kolExist[kolTemp - 1] = true;
                    } else {
                        return false;
                    }
                }
            }
        }

        return true;
    }
    
    public boolean possiblePlace (int kol, int rad) {
        int ruta = (rad / 3) * 3 + (kol / 3);
        
        boolean[] radExist = new boolean[9];
        boolean[] rutExist = new boolean[9];
        boolean[] kolExist = new boolean[9];
        
        Arrays.fill(radExist, false);
        Arrays.fill(rutExist, false);
        Arrays.fill(kolExist, false);
        
        for (int i = 0; i <= 8; i++) {
            int radTemp = rader[rad][i].getValue();
            int rutTemp = rutor[ruta][i].getValue();
            int kolTemp = kolumner[kol][i].getValue();
            
            if (radTemp == 0) {
                ;
            } else {
                if (!radExist[radTemp - 1]) {
                    radExist[radTemp - 1] = true;
                } else {
                    return false;
                }
            }
            
            if (rutTemp == 0) {
                ;
            } else {
                if (!rutExist[rutTemp - 1]) {
                    rutExist[rutTemp - 1] = true;
                } else {
                    return false;
                }
            }
            
            if (kolTemp == 0) {
                ;
            } else {
                if (!kolExist[kolTemp - 1]) {
                    kolExist[kolTemp - 1] = true;
                } else {
                    return false;
                }
            }
        }
        return true;
    }
    
    public boolean isFinished() {
        for (int i = 0; i <= 8; i++) {
            int sum = 0;
            for (int j = 0; j <= 8; j++) {
                sum = sum + rutor[i][j].getValue();
            }
            if (sum != 45) {
                return false;
            }
        }
        
        return true;
    }
    
    public boolean isFinished(int kol, int rad) {
        int ruta = (rad / 3) * 3 + (kol / 3);
        
        int kolSum = 0, radSum = 0, rutSum = 0;
        
        for (int i = 0; i <= 8; i++) {
            kolSum = kolSum + kolumner[kol][i].getValue();
            radSum = radSum + rader[rad][i].getValue();
            rutSum = rutSum + rutor[ruta][i].getValue();
        }
        
        if (kolSum != 45 || radSum != 45 || rutSum !=45) {
            return false;
        }
        
        return isFinished();
    }

    public MyInteger[][] solve() {
        MyInteger[][] returnValue = null;
        int rad = -1;
        int kol = -1;
        
        Koordinater koord = best();
        
        if (koord != null) {
            rad = koord.getRad();
            kol = koord.getKol();
        } else {
            for (int i = 0; i <= 8; i++) {
                for (int j = 0; j <= 8; j++) {
                    System.out.println(x++);
                    if (rader[i][j].getValue() == 0) {
                        rad = i;
                        kol = j;
                        break;
                    }
                }
                if (kol != -1) {
                    break;
                }
            }
        }
        
        if (kol == -1) {
            return null;
        }
        
        for (int k = 1; k <= 9; k++) {
            rader[rad][kol].setValue(k);
            
            //visa();
            
            if (possiblePlace(kol, rad)) {
            //if (possibleSudoku()) {
                if (!isFinished(kol, rad)) { //(j, i)) {
                    
                    returnValue = solve();
                    if (returnValue == null) {
                        ;
                    } else {
                        return returnValue;
                    }
                } else {
                    return rutor;
                }
            }
        }
        rader[rad][kol].setValue(0);
        return null;
    }

    public Koordinater best() {
        Koordinater ret = null;
        for (int i = 0; i <= 8; i++) {
            int radCount = 0, kolCount = 0, rutCount = 0;
            
            for (int j = 0; j <= 8; j++) {
                if (rader[i][j].getValue() != 0) {
                    radCount++;
                }
                if (kolumner[i][j].getValue() != 0) {
                    kolCount++;
                }
                if (rutor[i][j].getValue() != 0) {
                    rutCount++;
                }
                
            }
            if ((radCount == 8) || ((radCount == 7) && ret == null) ) {
                for (int j = 0; j <= 8; j++) {
                    if (rader[i][j].getValue() == 0) {
                        ret = new Koordinater(j, i);
                        if (radCount == 8) {
                            return ret;
                        }
                        break;
                    }
                }
            }
            
            if ((kolCount == 8) || ((kolCount == 7) && ret == null) ) {
                for (int j = 0; j <= 8; j++) {
                    if (kolumner[i][j].getValue() == 0) {
                        ret = new Koordinater(i, j);
                        if (radCount == 8) {
                            return ret;
                        }
                        break;
                    }
                }
            }
            
            if ((rutCount == 8) || ((rutCount == 7) && ret == null) ) {
                for (int j = 0; j <= 8; j++) {
                    if (rutor[i][j].getValue() == 0) {
                        ret = new Koordinater((i % 3) * 3 + (j % 3),
                                (i / 3) * 3 + (j / 3) );
                        if (rutCount == 8) {
                            return ret;
                        }
                        break;
                    }
                }
            }
        }
        
        return ret;
    }
    
    public void visa()  {
        wait(1000);
        
        for (int i = 0; i <= 8; i++) {
            for (int j = 0; j <= 8; j++) {
                int k = rutor[i][j].getValue();
                if (k == 0) {

                    textRutor[i][j].setText("");
                } else {
                    textRutor[i][j].setText("" + k);
                }
                textRutor[i][j].repaint();
                System.out.println(textRutor[i][j].getText() + "!");
            }
        }
    }

    public void wait (int n) {
        long t0, t1;
        
        t0 =  System.currentTimeMillis();

        do{
            t1 = System.currentTimeMillis();
        }
        while (t1 - t0 < n);

    }
    
    
    /*
    public MyInteger[][] solve1() {
        MyInteger[][] returnValue = null;
        
        for (int i = 0; i <= 8; i++) {
            for (int j = 0; j <= 8; j++) {
                System.out.println(x++);
                if (rader[i][j].getValue() == 0) {
                    for (int k = 1; k <= 9; k++) {
                        rader[i][j].setValue(k);
                        
                        if (possiblePlace(j, i)) {
                        //if (possibleSudoku()) {
                            if (!isFinished()) { //(j, i)) {
                                
                                returnValue = solve();
                                if (returnValue == null) {
                                    ;
                                } else {
                                    return returnValue;
                                }
                            } else {
                                return rutor;
                            }
                        }
                    }
                    rader[i][j].setValue(0);
                    return null;
                }
            }
        }
        return null;
    }
    */
}














